package cn.wh.beans.factory.support;

import cn.hutool.core.bean.BeanUtil;
import cn.wh.beans.BeansException;
import cn.wh.beans.PropertyValue;
import cn.wh.beans.PropertyValues;
import cn.wh.beans.factory.config.BeanDefinition;
import cn.wh.beans.factory.config.BeanReference;

import java.lang.reflect.Constructor;

/**
 * @author: wh
 * @create: 2022-08-19 16:56
 * @description
 **/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {

    CglibSubclassingInstantiationStrategy cglibSubclassingInstantiationStrategy = new CglibSubclassingInstantiationStrategy();

    public CglibSubclassingInstantiationStrategy getCglibSubclassingInstantiationStrategy() {
        return cglibSubclassingInstantiationStrategy;
    }

    public void setCglibSubclassingInstantiationStrategy(CglibSubclassingInstantiationStrategy cglibSubclassingInstantiationStrategy) {
        this.cglibSubclassingInstantiationStrategy = cglibSubclassingInstantiationStrategy;
    }

    @Override
    protected Object creatBean(String beanName, BeanDefinition beanDefinition, Object... args) {
        Object bean = null;
        try {
            bean = createBeanInstance(beanName, beanDefinition, args);
            //创建到单例容器中
            addSingletonBean(beanName, bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //实例化属性
        applyPropertyValues(beanName,bean,beanDefinition);
        return bean;
    }

    /**
     * 实例化bean
     *
     * @param beanName       bean名称
     * @param beanDefinition bean各种参数
     * @param args           构造函数参数
     * @return bean
     */
    protected Object createBeanInstance(String beanName, BeanDefinition beanDefinition, Object... args) {
        Constructor constructorUse = null;
        //判断构造函数参数个数是否与传入的参数个数一样
        Constructor[] constructors = beanDefinition.getBeanClass().getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            if (args != null && constructor.getParameterTypes().length == args.length) {
                constructorUse = constructor;
                break;
            }
        }
        return cglibSubclassingInstantiationStrategy.instantiate(beanDefinition, beanName, constructorUse, args);
    }

    /**
     * @param beanName
     * @param bean
     * @param beanDefinition
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        try {
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                Object value = propertyValue.getValue();
                String name = propertyValue.getName();
                if (value instanceof BeanReference){
                    //A依赖B 获取B的实例化
                    BeanReference beanReference=(BeanReference) value;
                    value=getBean(beanReference.getBeanName());
                }
                //属性填充
                BeanUtil.setFieldValue(bean,name,value);
            }
        } catch (Exception e) {
            throw new BeansException(""+beanName);
        }

    }

}
